package com.zx.idc.backend.gui.api.management.infosecurity.violationwebsite.management.service.impl;

import com.alibaba.fastjson.JSON;
import com.zx.idc.backend.gui.api.commom.entity.CommandModel;
import com.zx.idc.backend.gui.api.commom.entity.factory.CommandAckFactory;
import com.zx.idc.backend.gui.api.commom.template.IdcCommandTransferTemplate;
import com.zx.idc.backend.gui.api.commom.utils.ExternalHelper;
import com.zx.idc.backend.gui.api.management.infosecurity.violationwebsite.management.service.BlackListService;
import com.zx.idc.common.attributes.SchemaFileNameEnum;
import com.zx.idc.common.attributes.SystemAttributes;
import com.zx.idc.common.exception.EncryptException;
import com.zx.idc.common.exception.GlobalException;
import com.zx.idc.ds.base.house.entity.BaseHouseInfo;
import com.zx.idc.ds.base.house.service.IBaseHouseInfoService;
import com.zx.idc.ds.common.constant.ReportStatusConstant;
import com.zx.idc.ds.ins.entity.InsAdminControl;
import com.zx.idc.ds.ins.service.IInsAdminControlService;
import com.zx.idc.ds.sys.entity.SysBlackWhiteList;
import com.zx.idc.ds.sys.service.ISysBlackWhiteListService;
import com.zx.idc.internal.exception.SendMessageException;
import com.zx.idc.internal.ins.InstructionCallResult;
import com.zx.idc.internal.service.BlackListInstructionService;
import com.zx.idc.xml.entity.Blacklist;
import com.zx.idc.xml.entity.idccommandack.IdcCommandAck;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

import static com.zx.idc.common.constants.IdcCommandAckTypeConstants.ILLEGAL_WEBSITE_LIST_INSTRUCTION;

/**
 * Created by hasee on 2019/2/18.
 * 违法网站列表指令内容
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class BlackListServiceImpl implements BlackListService {
    private static final Integer BLACKLIST_TYPE_DOMAIN = 1;
    private static final Integer BLACKLIST_TYPE_IP = 2;
    private final static Logger LOG = LoggerFactory.getLogger(BlackListServiceImpl.class);

    @Autowired
    private IBaseHouseInfoService iBaseHouseInfoService;

    @Autowired
    private IInsAdminControlService iInsAdminControlService;

    @Autowired
    private ISysBlackWhiteListService iSysBlackWhiteListService;

    @Autowired
    private BlackListInstructionService blackListInstructionService;

    @Autowired
    private IdcCommandTransferTemplate idcCommandTransferTemplate;

    @Override
    public void blackList(Blacklist blacklist, CommandModel commandModel) {
        try {
            //1.添加到监管指令记录
            InsAdminControl entity = new InsAdminControl()
                .setCommandId(String.valueOf(blacklist.getCommandId()))
                .setInsType(SystemAttributes.INS_TYPE_ILLEGAL_WEBSITE_LIST)
                .setIdcId(blacklist.getIdcId())
                .setCreateTime(LocalDateTime.now())
                .setReportStatus(ReportStatusConstant.NOT_REPORTED)
                .setInsContents(JSON.toJSONString(blacklist));
            iInsAdminControlService.insert(entity);

            //获取idc的所有机房
            List<BaseHouseInfo> baseHouseInfos = iBaseHouseInfoService.selectList(new BaseHouseInfo().setIdcId(blacklist.getIdcId()));

            //2.添加/删除黑名单
            if (blacklist.getOperationType().equals(0)) {
                //新增
                SysBlackWhiteList sysBlackWhiteList = new SysBlackWhiteList();

                //7：域名屏蔽  //6：IP屏蔽
                final int category = Objects.equals(blacklist.getType(), BLACKLIST_TYPE_DOMAIN) ? 7 : 6;
                sysBlackWhiteList.setCreateTime(LocalDateTime.now())
                    .setCategory(category)
                    //6：违法网站
                    .setSource(SysBlackWhiteList.SOURCE_VIOLATION_WEBSITE)
                    .setPriority(blacklist.getLevel())
                    .setContent(blacklist.getContents())
                    //1：活跃 2：不活跃
                    .setStatus(1)
                    .setEditable(SysBlackWhiteList.ONLY_READ)
                    .setCommandId(blacklist.getCommandId())
                    .setComments("SMMS违法网站列表指令内容");
                iSysBlackWhiteListService.insert(sysBlackWhiteList);
                blacklist.setLevel(String.valueOf(Integer.parseInt(blacklist.getLevel(), 2)));

                //3.调用内部黑名单接口
                try {
                    if (baseHouseInfos != null && !baseHouseInfos.isEmpty()) {
                        for (BaseHouseInfo baseHouseInfo : baseHouseInfos) {
                            Long id = baseHouseInfo.getId();
                            String houseId = String.valueOf(id);
                            InstructionCallResult callResult = blackListInstructionService.addBlackList(blacklist, houseId);
                            if (callResult != null && callResult.getCode() == 200) {
                                LOG.info("添加黑名单发送成功");
                            } else {
                                LOG.error("添加黑名单发送失败,结果代码为:{}", callResult != null ? callResult.getCode() : 0);
                            }
                        }
                    }
                } catch (SendMessageException s) {
                    LOG.error("违法网站列表指令内容 添加黑名单失败", s);
                    throw s;
                } catch (EncryptException e) {
                    LOG.error("违法网站列表指令内容 添加黑名单加密/解密失败", e);
                    throw e;
                }
            } else if (blacklist.getOperationType().equals(1)) {
                //删除黑名单
                iSysBlackWhiteListService.delete(
                    new SysBlackWhiteList()
                        .setCommandId(blacklist.getCommandId())
                );

                //2进制转10进制
                blacklist.setLevel(String.valueOf(Integer.parseInt(blacklist.getLevel(), 2)));
                //3.调用内部黑名单接口
                try {
                    if (baseHouseInfos != null && !baseHouseInfos.isEmpty()) {
                        for (BaseHouseInfo baseHouseInfo : baseHouseInfos) {
                            String houseId = String.valueOf(baseHouseInfo.getId());
                            InstructionCallResult callResult = blackListInstructionService.delBlackList(blacklist, houseId);
                            if (callResult != null && callResult.getCode() == 200) {
                                LOG.info("删除黑名单发送成功");
                            } else {
                                LOG.error("删除黑名单发送失败,结果代码为:{}", callResult != null ? callResult.getCode() : 0);
                            }
                        }
                    }
                } catch (SendMessageException s) {
                    LOG.error("违法网站列表指令内容 删除黑名单失败", s);
                    throw s;
                } catch (EncryptException e) {
                    LOG.error("违法网站列表指令内容 删除黑名单加密/解密失败", e);
                    throw e;
                }
            }
            ExternalHelper.getExternalWebServiceEnable(() -> ackSusscess(blacklist, commandModel));
        } catch (Exception e) {
            LOG.error("违法网站列表指令出错 指令ID为:" + blacklist.getCommandId(), e);
            ExternalHelper.getExternalWebServiceEnable(() -> ackFailed(blacklist, commandModel));
            throw new RuntimeException("违法网站列表指令出错 指令ID为:" + blacklist.getCommandId(), e);
        }
    }

    private void ackSusscess(Blacklist blacklist, CommandModel commandModel) {
        //指令数据实体
        IdcCommandAck idcCommandAck = CommandAckFactory.ackSuccess(
            ILLEGAL_WEBSITE_LIST_INSTRUCTION,
            commandModel,
            commandAck ->
                commandAck.setCommandId(blacklist.getCommandId())
        );
        //调用回调接口
        LOG.debug("调用管局回调接口...");
        idcCommandTransferTemplate.transferTemplate(commandModel, idcCommandAck, SchemaFileNameEnum.INFO_SECURITY_MANAGEMENT);
    }

    private void ackFailed(Blacklist blacklist, CommandModel commandModel) {
        //指令数据实体
        IdcCommandAck idcCommandAck = CommandAckFactory.ackFail(
            ILLEGAL_WEBSITE_LIST_INSTRUCTION,
            commandModel,
            "网络错误，请销后重试!",
            commandAck ->
                commandAck.setCommandId(blacklist.getCommandId())
        );
        //调用回调接口
        LOG.debug("调用管局回调接口...");
        idcCommandTransferTemplate.transferTemplate(commandModel, idcCommandAck, SchemaFileNameEnum.INFO_SECURITY_MANAGEMENT);
    }
}
